package org.eliza.base.coroutinesx.flow

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking


//flow接收的lambda表达式是一个协程环境，里面的操作实在一个协程中执行
//collect是收集操作，只有收集时才会真的去执行流中定义的逻辑
//flow也可以被取消
private fun flowx() {

    val flow = flow {
        // 耗时操作1
        delay(200)
        emit(12)
        // 耗时操作2
        delay(200)
        emit(13)
    }
    println("flow init")
    runBlocking {
        flow.collect { println(it) } //collect是收集操作，只有收集时才会真的去执行流中定义的逻辑
    }
}


private fun simpleList(): List<Int> = listOf(1, 2, 3)


private fun simpleSequence(): Sequence<Int> = sequence { // sequence builder
    for (i in 1..3) {
        Thread.sleep(100) // pretend we are computing it
        yield(i) // yield next value
    }
}


private suspend fun simple(): List<Int> {
    println("====simple====")
    delay(1000) // pretend we are doing something asynchronous here
    return listOf(1, 2, 3)
}

private fun runBlockingSimple() = runBlocking<Unit> {
    println("====runBlockingSimple====")
    simple().forEach { value -> println(value) }
}

private fun flowSimple(): Flow<Int> = flow { // flow builder
    for (i in 1..3) {
        delay(100) // pretend we are doing something useful here
        emit(i) // emit next value
    }
}

private fun runFlowSimple() = runBlocking<Unit> {
    println("====runFlowSimple====")

    // Launch a concurrent coroutine to check if the main thread is blocked
    launch {
        for (k in 1..3) {
            println("I'm not blocked $k")
            delay(100)
        }
    }
    // Collect the flow
    flowSimple().collect { value -> println(value) }
}


//=========

private fun flowEmit(): Flow<Int> = flow {
    println("Flow started")
    for (i in 1..3) {
        delay(100)
        emit(i)
    }
}
private fun runFlowEmit() = runBlocking<Unit> {
    println("====runFlowEmit====")
    val flow = flowEmit()
    println("runFlowEmit=>Calling collect...")
    flow.collect { value -> println(value) }
    println("runFlowEmit=>Calling collect again...")
    flow.collect { value -> println(value) }
}

private fun main() {
    simpleList().forEach {}
    simpleSequence().forEach { va -> println(va) }
    runBlockingSimple()
    runFlowSimple()
    runFlowEmit()
}